using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using SpriteGame.UI;
using SpriteGame.Helpers;
using Microsoft.Xna.Framework.Input;
using FarseerPhysics.Dynamics;
using SpriteGame.Entities;

namespace SpriteGame.Scenes
{
    enum GameState
    {
        NONE,
        STARTGAME,
        AIMING,
        CHARGEING,
        FIRED,
        SCOREING,
        MOVENEXT,
        ENDGAME
    }

    class MultiplayerGame:Scene
    {
        GameState lastState = GameState.NONE;
        GameState currentState = GameState.NONE;

        //Player variables
        Player[] players = new Player[4];
        int currentPlayer = 0;

        UIPercentageBar p1Health;
        UIPercentageBar p2Health;
        UIPercentageBar p3Health;
        UIPercentageBar p4Health;
        Vector2 playerCameraOffset = new Vector2(0, 15);


        UIPercentageBar powerBar;

        //Gamestate variables
        //Startgame
        Vector2 gameStartCamera = new Vector2(0, 25);

        //Aim
        Vector2 fireAngle = Vector2.Zero;
        //FireBall
        BaseSprite followTarget = null;
        public BaseSprite FollowTarget
        {
            get{ return followTarget; }
        }

        //UI variables
        UIImage startGraphics;
        UIText gamepadOutput;

        bool playersSpawned = false;

        string levelName = "";

        public MultiplayerGame(Game1 _parent)
            : base(_parent)
        {
            IsActive = true;

        }

        public MultiplayerGame(Game1 _parent, string _levelName)
            : base(_parent)
        {
            IsActive = true;
            levelName = _levelName;
        }

        public override void RemoveEntity(BaseSprite _e)
        {
            if (followTarget == _e)
            {
                followTarget = null;
            }
            base.RemoveEntity(_e);
        }

        public override void LoadContent()
        {
            base.LoadContent();
            PausedPhysics = true;
            LoadScene(levelName);
            parent.ViewCenterAdd(new Vector2(Rand.RandomFloat(-400, 400), Rand.RandomFloat(10000, 10000)));
            //AudioManager.SoundManager.PlaySong("GamePlay", true);
            //AudioManager.SoundManager.StopSong();
            //AudioManager.SoundManager.StopAllSounds();
        }

        public override void BuildHUD()
        {
            base.BuildHUD();

            int screenWidth = parent.GraphicsDevice.Viewport.Width;
            int screenHeight = parent.GraphicsDevice.Viewport.Height;
            int middle = screenWidth / 2;
            int middleV = screenHeight / 2;

            startGraphics = new UIImage(middle - 400, middleV - 300, 800, 600, "Textures/UI/HUD/StartGameGraphics");
            startGraphics.IsVisible = false;
            Hud.AddChild(startGraphics);

            gamepadOutput = new UIText(0, 0, 100, 50, "{0,0}");
            Hud.AddChild(gamepadOutput);

            Hud.AddChild(new UIImage(10, 10, 108, 12, "Textures/UI/P1"));
            Hud.AddChild(new UIImage(230, 10, 108, 12, "Textures/UI/P2"));
            Hud.AddChild(new UIImage(448, 10, 108, 12, "Textures/UI/P3"));
            Hud.AddChild(new UIImage(666, 10, 108, 12, "Textures/UI/P4"));

            p1Health = new UIPercentageBar(118, 10, 100, 12, "Textures/UI/Health");
            p2Health = new UIPercentageBar(338, 10, 100, 12, "Textures/UI/Health");
            p3Health = new UIPercentageBar(556, 10, 100, 12, "Textures/UI/Health");
            p4Health = new UIPercentageBar(774, 10, 100, 12, "Textures/UI/Health");

            powerBar = new UIPercentageBar(10, 700, 1290, 20, "Textures/UI/Health");
            powerBar.IsVisible = false;

            Hud.AddChild(p1Health);
            Hud.AddChild(p2Health);
            Hud.AddChild(p3Health);
            Hud.AddChild(p4Health);
            Hud.AddChild(powerBar);

            Hud.IsVisible = false;
        }

        int timeout = 0;

        public override void Update(GameTime _time)
        {

            if(playersSpawned)
            {
                switch (currentState)
                {
                    case (GameState.NONE):


                        if (currentPlayer == 0 && lastState == GameState.NONE)
                        {
                            if (timeout > 300)
                            {
                                Hud.IsVisible = true;
                                parent.ViewCenterAdd(new Vector2(0, Rand.RandomFloat(100, 100)));
                                parent.ResetLerp();
                                PausedPhysics = false;
                                currentState = GameState.STARTGAME;
                            }
                            else
                            {
                                timeout++;
                            }
                        }

                        break;
                    case (GameState.STARTGAME):
                        startGraphics.IsVisible = true;
                        startGame(_time);
                        break;
                    case (GameState.MOVENEXT):
                        moveNext(_time);
                        break;
                    case (GameState.AIMING):
                        aiming(_time);
                        break;
                    case (GameState.CHARGEING):
                        chargeing(_time);
                        break;
                    case (GameState.FIRED):
                        fired(_time);
                        break;
                    case (GameState.SCOREING):
                        scoreing(_time);
                        break;
                    case (GameState.ENDGAME):
                        break;
                }
                p1Health.Percentage = players[0].Health * 0.01f;
                p2Health.Percentage = players[1].Health * 0.01f;
                p3Health.Percentage = players[2].Health * 0.01f;
                p4Health.Percentage = players[3].Health * 0.01f;
            }
            base.Update(_time);
            if (!playersSpawned)
            {

                int entLength = entities.Count - 1;
                BaseSprite ent = entities[entLength];
                Vector2 playerPos1 = ent.Position;
                RemoveEntity(ent);
                ent = entities[entLength - 1];
                Vector2 playerPos2 = ent.Position;
                RemoveEntity(ent);
                ent = entities[entLength - 2];
                Vector2 playerPos3 = ent.Position;
                RemoveEntity(ent);
                ent = entities[entLength - 3];
                Vector2 playerPos4 = ent.Position;
                RemoveEntity(ent);

                players[0] = new Player(this, BodyType.Dynamic, playerPos1, 0.0f, "Textures/Player");
                //players[0].Body.Awake = false;
                players[1] = new Player(this, BodyType.Dynamic, playerPos2, 0.0f, "Textures/Player");
                //players[1].Body.Awake = false;
                players[2] = new Player(this, BodyType.Dynamic, playerPos3, 0.0f, "Textures/Player");
                //players[2].IsDead = true;
                // players[2].Body.Awake = false;
                players[3] = new Player(this, BodyType.Dynamic, playerPos4, 0.0f, "Textures/Player");
                //players[3].IsDead = true;
                //players[3].Body.Awake = false;
                //players[3].Body.Active = false;
                players[0].Body.FixedRotation = true;
                players[1].Body.FixedRotation = true;
                players[2].Body.FixedRotation = true;
                players[3].Body.FixedRotation = true;
                AddEntity(players);

                playersSpawned = true;
            }
        }

        void startGame(GameTime _time)
        {
            //Slide the camera onto the level
            if (parent.ViewCenter.Length() > .001f)
            {
                parent.LerpCamera(gameStartCamera, 0.2f);
            }
            else
            {
                parent.SetViewCenter(gameStartCamera);
            }

            if(InputHandler.IsGamepadButtonPressed(Buttons.A))
            {
                if (parent.ViewCenter != gameStartCamera)
                {
                    parent.SetViewCenter(gameStartCamera);
                }

                startGraphics.IsVisible = false;
                selectNextPlayer();
                parent.ResetLerp();
                currentState = GameState.MOVENEXT;
            }
        }

        void moveNext(GameTime _time)
        {
            Vector2 playerPos = players[currentPlayer].Position + playerCameraOffset;
            Vector2 dist = playerPos - parent.ViewCenter;
            if (dist.Length() > 0.1f)
            {
                parent.LerpCamera(playerPos, 0.2f);
            }
            else
            {
                parent.SetViewCenter(playerPos);
                parent.ResetLerp();
                players[currentPlayer].IsAiming = true;
                currentState = GameState.AIMING;
            }
        }

        void aiming(GameTime _time)
        {
            //parent.SetZoom(1 - (InputHandler.GetThumbstickVector(false).Y * 0.8f));
            Vector2 playerPosition = players[currentPlayer].Position;
            Vector2 thumbVector = InputHandler.GetThumbstickVector(true);
            parent.LerpCamera(playerCameraOffset + playerPosition + (thumbVector * 25), 0.1f);
            float angle = (float)Math.Atan2(-thumbVector.X, thumbVector.Y);
            players[currentPlayer].AimRot = angle;
            if (InputHandler.IsGamepadButtonPressed(Buttons.RightShoulder))
            {
                aimVector = thumbVector;
                powerBar.IsVisible = true;
                parent.ResetLerp();
                currentState = GameState.CHARGEING;
                //parent.ViewZoom = 0.2f;
            }
            if (InputHandler.IsGamepadButtonPressed(Buttons.LeftShoulder))
            {
                singularity = true;
            }
        }

        bool singularity = false;

        Vector2 aimVector = Vector2.Zero;
        float chargeValue = 0.01f;

        void chargeing(GameTime _time)
        {
            chargeValue += 0.01f;
            powerBar.Percentage = chargeValue;
            if (InputHandler.IsGamepadButtonReleased(Buttons.RightShoulder) || chargeValue >= 1)
            {
                Vector2 playerPosition = players[currentPlayer].Position;
                Vector2 fireForce = InputHandler.GetThumbstickVector(true) * (5000 * chargeValue);
                Ball s;
                if (!singularity)
                {
                    s = new Ball(this, 1.6f, 1.6f, BodyType.Dynamic, playerPosition, 0.0f, "Textures/Debug/DebugBall");
                }
                else
                {
                    s = new GravityBall(this, 1.6f, 1.6f, BodyType.Dynamic, playerPosition, 0.0f, "Textures/Debug/DebugBall");
                    singularity = false;
                }
                AddEntity(s);
                s.Body.ApplyForce(ref fireForce);
                s.Body.IsBullet = true;
                followTarget = s;
                players[currentPlayer].Body.Awake = false;
                players[currentPlayer].IsAiming = false;
                players[currentPlayer].Body.Active = false;
                powerBar.IsVisible = false;
                chargeValue = 0.01f;
                currentState = GameState.FIRED;
                lastPos = s.Position;
            }
        }

        Vector2 lastPos = Vector2.Zero;

        void fired(GameTime _time)
        {
            if (followTarget != null)
            {
                parent.LerpCamera(Vector2.Lerp(followTarget.Position, lastPos, 0.5f), 0.1f);
                lastPos = followTarget.Position;

                Particles.AddParticle(lastPos, Vector2.Zero);
                
                Vector2 playerToBall = players[currentPlayer].Position - followTarget.Position;

                if (playerToBall.Length() > 5)
                {
                    players[currentPlayer].Body.Awake = true;
                    players[currentPlayer].Body.Active = true;
                }
            }
            else
            {
                players[currentPlayer].Body.Awake = true;
                players[currentPlayer].Body.Active = true;
                selectNextPlayer();
                parent.ResetLerp();
                scoreCount = 0;
                currentState = GameState.SCOREING;
            }
        }

        int scoreCount = 0;

        void scoreing(GameTime _time)
        {
            scoreCount++;

            if (scoreCount > 200)
            {
                scoreCount = 0;
                parent.ResetLerp();
                currentState = GameState.MOVENEXT;
            }
        }

        void selectNextPlayer()
        {
            do
            {
                currentPlayer++;

                if (currentPlayer > 3)
                {
                    currentPlayer = 0;
                }
            }
            while (players[currentPlayer] == null || players[currentPlayer].IsDead == true);
        }
    }
}